package lq.auth.studyauth.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.wf.captcha.GifCaptcha;
import com.wf.captcha.SpecCaptcha;
import com.wf.captcha.base.Captcha;
import lq.auth.studyauth.properties.StudyAuthProperties;
import lq.auth.studyauth.properties.StudyValidateCodeProperties;
import lq.common.entity.StudyConstant;
import lq.common.exception.ValidateCodeException;
import lq.common.service.RedisService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.swing.text.DefaultCaret;
import java.io.IOException;

/**
 * 验证码service
 */
@Service
public class ValidateCodeService {

    @Autowired
    private RedisService redisService;
    @Autowired
    private StudyAuthProperties properties;

    /**
     * 创建验证码
     *
     * @param request  因为前后端分离,不再基于session,我们需要客户端(浏览器)请求的时候,
     *                 携带一个key(按照某种算法随机生成的字符串,模拟jsessionid)来和验证码一一对应
     * @param response
     * @throws ValidateCodeException
     */
    public void create(HttpServletRequest request, HttpServletResponse response) throws ValidateCodeException, IOException {
        String key = request.getParameter("key");
        if (StringUtils.isBlank(key)) {
            throw new ValidateCodeException("验证码key不能为空");
        }
        StudyValidateCodeProperties code = properties.getCode();
        setHeader(response, code.getType());

        Captcha captcha = createCaptcha(code);
        // 验证码写入redis,将常量类定义的验证码前缀加上key作为验证码的key
        redisService.set(StudyConstant.CODE_PREFIX + key, StringUtils.lowerCase(captcha.text()), code.getTime());
        captcha.out(response.getOutputStream());
    }

    /**
     * 验证码验证
     * @param key
     * @param value
     * @throws ValidateCodeException
     */
    public void check(String key, String value) throws ValidateCodeException {
        // 根据key从redis获取验证码
        Object codeInRedis = redisService.get(StudyConstant.CODE_PREFIX + key);
        if (StringUtils.isBlank(value)) {
            throw new ValidateCodeException("请输入验证码");
        }
        if (codeInRedis == null) {
            throw new ValidateCodeException("验证码已经过期");
        }
        if (!StringUtils.equalsIgnoreCase(value, String.valueOf(codeInRedis))) {
            throw new ValidateCodeException("验证码不正确");
        }
    }

    /**
     * 生成验证码
     * 根据配置设置验证码格式,长宽高等信息
     *
     * @param code 验证码配置信息
     * @return
     */
    private Captcha createCaptcha(StudyValidateCodeProperties code) {
        Captcha captcha = null;
        if (StringUtils.equalsIgnoreCase(code.getType(), StudyConstant.GIF)) {
            captcha = new GifCaptcha(code.getWidth(), code.getHeight(), code.getLength());
        } else {
            captcha = new SpecCaptcha(code.getWidth(), code.getHeight(), code.getLength());
        }
        captcha.setCharType(code.getCharType());
        return captcha;
    }

    /**
     * 设置请求头
     *
     * @param response
     * @param type
     */
    private void setHeader(HttpServletResponse response, String type) {
        if (StringUtils.equals(type, StudyConstant.GIF)) {
            response.setContentType(MediaType.IMAGE_GIF_VALUE);
        }
        if (StringUtils.equals(type, StudyConstant.PNG)) {
            response.setContentType(MediaType.IMAGE_PNG_VALUE);
        }
        response.setHeader(HttpHeaders.PRAGMA, "No-cache");
        response.setHeader(HttpHeaders.CACHE_CONTROL, "No-cache");
        response.setDateHeader(HttpHeaders.EXPIRES, 0L);
    }

}
